home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / include / bits / mathinline.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  26KB  |  756 lines

  1. /* Inline math functions for i387.
  2.    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
  3.    Free Software Foundation, Inc.
  4.    This file is part of the GNU C Library.
  5.    Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
  6.  
  7.    The GNU C Library is free software; you can redistribute it and/or
  8.    modify it under the terms of the GNU Lesser General Public
  9.    License as published by the Free Software Foundation; either
  10.    version 2.1 of the License, or (at your option) any later version.
  11.  
  12.    The GNU C Library is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.    Lesser General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU Lesser General Public
  18.    License along with the GNU C Library; if not, write to the Free
  19.    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  20.    02111-1307 USA.  */
  21.  
  22. #ifndef _MATH_H
  23. # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
  24. #endif
  25.  
  26. #ifdef __cplusplus
  27. # define __MATH_INLINE __inline
  28. #else
  29. # define __MATH_INLINE extern __inline
  30. #endif
  31.  
  32.  
  33. #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
  34. /* GCC 2.97 and up have builtins that actually can be used.  */
  35. # if !__GNUC_PREREQ (2,97)
  36. /* ISO C99 defines some macros to perform unordered comparisons.  The
  37.    ix87 FPU supports this with special opcodes and we should use them.
  38.    These must not be inline functions since we have to be able to handle
  39.    all floating-point types.  */
  40. #  undef isgreater
  41. #  undef isgreaterequal
  42. #  undef isless
  43. #  undef islessequal
  44. #  undef islessgreater
  45. #  undef isunordered
  46. #  ifdef __i686__
  47. /* For the PentiumPro and more recent processors we can provide
  48.    better code.  */
  49. #   define isgreater(x, y) \
  50.      ({ register char __result;                              \
  51.     __asm__ ("fucomip %%st(1), %%st; seta %%al"                  \
  52.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
  53.     __result; })
  54. #   define isgreaterequal(x, y) \
  55.      ({ register char __result;                              \
  56.     __asm__ ("fucomip %%st(1), %%st; setae %%al"                  \
  57.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
  58.     __result; })
  59.  
  60. #   define isless(x, y) \
  61.      ({ register char __result;                              \
  62.     __asm__ ("fucomip %%st(1), %%st; seta %%al"                  \
  63.          : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
  64.     __result; })
  65.  
  66. #   define islessequal(x, y) \
  67.      ({ register char __result;                              \
  68.     __asm__ ("fucomip %%st(1), %%st; setae %%al"                  \
  69.          : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
  70.     __result; })
  71.  
  72. #   define islessgreater(x, y) \
  73.      ({ register char __result;                              \
  74.     __asm__ ("fucomip %%st(1), %%st; setne %%al"                  \
  75.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
  76.     __result; })
  77.  
  78. #   define isunordered(x, y) \
  79.      ({ register char __result;                              \
  80.     __asm__ ("fucomip %%st(1), %%st; setp %%al"                  \
  81.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
  82.     __result; })
  83. #  else
  84. /* This is the dumb, portable code for i386 and above.  */
  85. #   define isgreater(x, y) \
  86.      ({ register char __result;                              \
  87.     __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"          \
  88.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
  89.     __result; })
  90.  
  91. #   define isgreaterequal(x, y) \
  92.      ({ register char __result;                              \
  93.     __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"          \
  94.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
  95.     __result; })
  96.  
  97. #   define isless(x, y) \
  98.      ({ register char __result;                              \
  99.     __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"          \
  100.          : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
  101.     __result; })
  102.  
  103. #   define islessequal(x, y) \
  104.      ({ register char __result;                              \
  105.     __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"          \
  106.          : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
  107.     __result; })
  108.  
  109. #   define islessgreater(x, y) \
  110.      ({ register char __result;                              \
  111.     __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al"          \
  112.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
  113.     __result; })
  114.  
  115. #   define isunordered(x, y) \
  116.      ({ register char __result;                              \
  117.     __asm__ ("fucompp; fnstsw; sahf; setp %%al"                  \
  118.          : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
  119.     __result; })
  120. #  endif /* __i686__ */
  121. # endif    /* GCC 2.97 */
  122.  
  123. /* The gcc, version 2.7 or below, has problems with all this inlining
  124.    code.  So disable it for this version of the compiler.  */
  125. # if __GNUC_PREREQ (2, 8)
  126. /* Test for negative number.  Used in the signbit() macro.  */
  127. __MATH_INLINE int
  128. __NTH (__signbitf (float __x))
  129. {
  130.   __extension__ union { float __f; int __i; } __u = { __f: __x };
  131.   return __u.__i < 0;
  132. }
  133. __MATH_INLINE int
  134. __NTH (__signbit (double __x))
  135. {
  136.   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
  137.   return __u.__i[1] < 0;
  138. }
  139. __MATH_INLINE int
  140. __NTH (__signbitl (long double __x))
  141. {
  142.   __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
  143.   return (__u.__i[2] & 0x8000) != 0;
  144. }
  145. # endif
  146. #endif
  147.  
  148.  
  149. /* The gcc, version 2.7 or below, has problems with all this inlining
  150.    code.  So disable it for this version of the compiler.  */
  151. #if __GNUC_PREREQ (2, 8)
  152.  
  153. #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
  154.      && defined __OPTIMIZE__)
  155.  
  156. /* A macro to define float, double, and long double versions of various
  157.    math functions for the ix87 FPU.  FUNC is the function name (which will
  158.    be suffixed with f and l for the float and long double version,
  159.    respectively).  OP is the name of the FPU operation.
  160.    We define two sets of macros.  The set with the additional NP
  161.    doesn't add a prototype declaration.  */
  162.  
  163. #if defined __USE_MISC || defined __USE_ISOC99
  164. # define __inline_mathop(func, op) \
  165.   __inline_mathop_ (double, func, op)                          \
  166.   __inline_mathop_ (float, __CONCAT(func,f), op)                  \
  167.   __inline_mathop_ (long double, __CONCAT(func,l), op)
  168. # define __inline_mathopNP(func, op) \
  169.   __inline_mathopNP_ (double, func, op)                          \
  170.   __inline_mathopNP_ (float, __CONCAT(func,f), op)                  \
  171.   __inline_mathopNP_ (long double, __CONCAT(func,l), op)
  172. #else
  173. # define __inline_mathop(func, op) \
  174.   __inline_mathop_ (double, func, op)
  175. # define __inline_mathopNP(func, op) \
  176.   __inline_mathopNP_ (double, func, op)
  177. #endif
  178.  
  179. #define __inline_mathop_(float_type, func, op) \
  180.   __inline_mathop_decl_ (float_type, func, op, "0" (__x))
  181. #define __inline_mathopNP_(float_type, func, op) \
  182.   __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
  183.  
  184.  
  185. #if defined __USE_MISC || defined __USE_ISOC99
  186. # define __inline_mathop_decl(func, op, params...) \
  187.   __inline_mathop_decl_ (double, func, op, params)                  \
  188.   __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)              \
  189.   __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
  190. # define __inline_mathop_declNP(func, op, params...) \
  191.   __inline_mathop_declNP_ (double, func, op, params)                  \
  192.   __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params)              \
  193.   __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
  194. #else
  195. # define __inline_mathop_decl(func, op, params...) \
  196.   __inline_mathop_decl_ (double, func, op, params)
  197. # define __inline_mathop_declNP(func, op, params...) \
  198.   __inline_mathop_declNP_ (double, func, op, params)
  199. #endif
  200.  
  201. #define __inline_mathop_decl_(float_type, func, op, params...) \
  202.   __MATH_INLINE float_type func (float_type) __THROW;                  \
  203.   __inline_mathop_declNP_ (float_type, func, op, params)
  204.  
  205. #define __inline_mathop_declNP_(float_type, func, op, params...) \
  206.   __MATH_INLINE float_type __NTH (func (float_type __x))              \
  207.   {                                          \
  208.     register float_type __result;                          \
  209.     __asm __volatile__ (op : "=t" (__result) : params);                  \
  210.     return __result;                                  \
  211.   }
  212.  
  213.  
  214. #if defined __USE_MISC || defined __USE_ISOC99
  215. # define __inline_mathcode(func, arg, code) \
  216.   __inline_mathcode_ (double, func, arg, code)                      \
  217.   __inline_mathcode_ (float, __CONCAT(func,f), arg, code)              \
  218.   __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
  219. # define __inline_mathcodeNP(func, arg, code) \
  220.   __inline_mathcodeNP_ (double, func, arg, code)                  \
  221.   __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code)              \
  222.   __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
  223. # define __inline_mathcode2(func, arg1, arg2, code) \
  224.   __inline_mathcode2_ (double, func, arg1, arg2, code)                  \
  225.   __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)          \
  226.   __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
  227. # define __inline_mathcodeNP2(func, arg1, arg2, code) \
  228.   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)              \
  229.   __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code)          \
  230.   __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
  231. # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
  232.   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)              \
  233.   __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)          \
  234.   __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
  235. # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
  236.   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)              \
  237.   __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)     \
  238.   __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
  239. #else
  240. # define __inline_mathcode(func, arg, code) \
  241.   __inline_mathcode_ (double, func, (arg), code)
  242. # define __inline_mathcodeNP(func, arg, code) \
  243.   __inline_mathcodeNP_ (double, func, (arg), code)
  244. # define __inline_mathcode2(func, arg1, arg2, code) \
  245.   __inline_mathcode2_ (double, func, arg1, arg2, code)
  246. # define __inline_mathcodeNP2(func, arg1, arg2, code) \
  247.   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
  248. # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
  249.   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
  250. # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
  251.   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
  252. #endif
  253.  
  254. #define __inline_mathcode_(float_type, func, arg, code) \
  255.   __MATH_INLINE float_type func (float_type) __THROW;                  \
  256.   __inline_mathcodeNP_(float_type, func, arg, code)
  257.  
  258. #define __inline_mathcodeNP_(float_type, func, arg, code) \
  259.   __MATH_INLINE float_type __NTH (func (float_type arg))              \
  260.   {                                          \
  261.     code;                                      \
  262.   }
  263.  
  264.  
  265. #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
  266.   __MATH_INLINE float_type func (float_type, float_type) __THROW;          \
  267.   __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
  268.  
  269. #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
  270.   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2))    \
  271.   {                                          \
  272.     code;                                      \
  273.   }
  274.  
  275. #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
  276.   __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
  277.   __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
  278.  
  279. #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
  280.   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2,     \
  281.                     float_type arg3))              \
  282.   {                                          \
  283.     code;                                      \
  284.   }
  285. #endif
  286.  
  287.  
  288. #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
  289. /* Miscellaneous functions */
  290.  
  291. __inline_mathcode (__sgn, __x, \
  292.   return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
  293.  
  294. /* __FAST_MATH__ is defined by gcc -ffast-math.  */
  295. #ifdef __FAST_MATH__
  296. __inline_mathcode (__pow2, __x, \
  297.   register long double __value;                              \
  298.   register long double __exponent;                          \
  299.   __extension__ long long int __p = (long long int) __x;              \
  300.   if (__x == (long double) __p)                              \
  301.     {                                          \
  302.       __asm __volatile__                              \
  303.     ("fscale"                                  \
  304.      : "=t" (__value) : "0" (1.0), "u" (__x));                  \
  305.       return __value;                                  \
  306.     }                                          \
  307.   __asm __volatile__                                  \
  308.     ("fld    %%st(0)\n\t"                              \
  309.      "frndint            # int(x)\n\t"                      \
  310.      "fxch\n\t"                                      \
  311.      "fsub    %%st(1)        # fract(x)\n\t"                      \
  312.      "f2xm1            # 2^(fract(x)) - 1\n\t"                  \
  313.      : "=t" (__value), "=u" (__exponent) : "0" (__x));                  \
  314.   __value += 1.0;                                  \
  315.   __asm __volatile__                                  \
  316.     ("fscale"                                      \
  317.      : "=t" (__value) : "0" (__value), "u" (__exponent));              \
  318.   return __value)
  319.  
  320. # ifdef __USE_GNU
  321. #  define __sincos_code \
  322.   register long double __cosr;                              \
  323.   register long double __sinr;                              \
  324.   __asm __volatile__                                  \
  325.     ("fsincos\n\t"                                  \
  326.      "fnstsw    %%ax\n\t"                              \
  327.      "testl    $0x400, %%eax\n\t"                          \
  328.      "jz    1f\n\t"                                  \
  329.      "fldpi\n\t"                                  \
  330.      "fadd    %%st(0)\n\t"                              \
  331.      "fxch    %%st(1)\n\t"                              \
  332.      "2: fprem1\n\t"                                  \
  333.      "fnstsw    %%ax\n\t"                              \
  334.      "testl    $0x400, %%eax\n\t"                          \
  335.      "jnz    2b\n\t"                                  \
  336.      "fstp    %%st(1)\n\t"                              \
  337.      "fsincos\n\t"                                  \
  338.      "1:"                                      \
  339.      : "=t" (__cosr), "=u" (__sinr) : "0" (__x));                  \
  340.   *__sinx = __sinr;                                  \
  341.   *__cosx = __cosr
  342.  
  343. __MATH_INLINE void
  344. __NTH (__sincos (double __x, double *__sinx, double *__cosx))
  345. {
  346.   __sincos_code;
  347. }
  348.  
  349. __MATH_INLINE void
  350. __NTH (__sincosf (float __x, float *__sinx, float *__cosx))
  351. {
  352.   __sincos_code;
  353. }
  354.  
  355. __MATH_INLINE void
  356. __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
  357. {
  358.   __sincos_code;
  359. }
  360. # endif
  361.  
  362.  
  363. /* Optimized inline implementation, sometimes with reduced precision
  364.    and/or argument range.  */
  365.  
  366. # if __GNUC_PREREQ (3, 5)
  367. #  define __expm1_code \
  368.   register long double __temp;                              \
  369.   __temp = __builtin_expm1l (__x);                          \
  370.   return __temp ? __temp : __x
  371. # else
  372. #  define __expm1_code \
  373.   register long double __value;                              \
  374.   register long double __exponent;                          \
  375.   register long double __temp;                              \
  376.   __asm __volatile__                                  \
  377.     ("fldl2e            # e^x - 1 = 2^(x * log2(e)) - 1\n\t"          \
  378.      "fmul    %%st(1)        # x * log2(e)\n\t"                  \
  379.      "fst    %%st(1)\n\t"                              \
  380.      "frndint            # int(x * log2(e))\n\t"                  \
  381.      "fxch\n\t"                                      \
  382.      "fsub    %%st(1)        # fract(x * log2(e))\n\t"              \
  383.      "f2xm1            # 2^(fract(x * log2(e))) - 1\n\t"          \
  384.      "fscale            # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
  385.      : "=t" (__value), "=u" (__exponent) : "0" (__x));                  \
  386.   __asm __volatile__                                  \
  387.     ("fscale            # 2^int(x * log2(e))\n\t"              \
  388.      : "=t" (__temp) : "0" (1.0), "u" (__exponent));                  \
  389.   __temp -= 1.0;                                  \
  390.   __temp += __value;                                  \
  391.   return __temp ? __temp : __x
  392. # endif
  393. __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
  394.  
  395. # if __GNUC_PREREQ (3, 4)
  396. __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
  397. # else
  398. #  define __exp_code \
  399.   register long double __value;                              \
  400.   register long double __exponent;                          \
  401.   __asm __volatile__                                  \
  402.     ("fldl2e            # e^x = 2^(x * log2(e))\n\t"              \
  403.      "fmul    %%st(1)        # x * log2(e)\n\t"                  \
  404.      "fst    %%st(1)\n\t"                              \
  405.      "frndint            # int(x * log2(e))\n\t"                  \
  406.      "fxch\n\t"                                      \
  407.      "fsub    %%st(1)        # fract(x * log2(e))\n\t"              \
  408.      "f2xm1            # 2^(fract(x * log2(e))) - 1\n\t"          \
  409.      : "=t" (__value), "=u" (__exponent) : "0" (__x));                  \
  410.   __value += 1.0;                                  \
  411.   __asm __volatile__                                  \
  412.     ("fscale"                                      \
  413.      : "=t" (__value) : "0" (__value), "u" (__exponent));              \
  414.   return __value
  415. __inline_mathcodeNP (exp, __x, __exp_code)
  416. __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
  417. # endif
  418.  
  419.  
  420. # if !__GNUC_PREREQ (3, 5)
  421. __inline_mathcodeNP (tan, __x, \
  422.   register long double __value;                              \
  423.   register long double __value2 __attribute__ ((__unused__));              \
  424.   __asm __volatile__                                  \
  425.     ("fptan"                                      \
  426.      : "=t" (__value2), "=u" (__value) : "0" (__x));                  \
  427.   return __value)
  428. # endif
  429. #endif /* __FAST_MATH__ */
  430.  
  431.  
  432. #if __GNUC_PREREQ (3, 4)
  433. __inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
  434.                return __builtin_atan2l (__y, __x))
  435. #else
  436. # define __atan2_code \
  437.   register long double __value;                              \
  438.   __asm __volatile__                                  \
  439.     ("fpatan"                                      \
  440.      : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)");              \
  441.   return __value
  442. # ifdef __FAST_MATH__
  443. __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
  444. # endif
  445. __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
  446. #endif
  447.  
  448.  
  449. #if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
  450. __inline_mathcodeNP2 (fmod, __x, __y, \
  451.   register long double __value;                              \
  452.   __asm __volatile__                                  \
  453.     ("1:    fprem\n\t"                              \
  454.      "fnstsw    %%ax\n\t"                              \
  455.      "sahf\n\t"                                      \
  456.      "jp    1b"                                  \
  457.      : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");              \
  458.   return __value)
  459. #endif
  460.  
  461.  
  462. #ifdef __FAST_MATH__
  463. # if !__GNUC_PREREQ (3,3)
  464. __inline_mathopNP (sqrt, "fsqrt")
  465. __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
  466. #  define __libc_sqrtl(n) __sqrtl (n)
  467. # else
  468. #  define __libc_sqrtl(n) __builtin_sqrtl (n)
  469. # endif
  470. #endif
  471.  
  472. #if __GNUC_PREREQ (2, 8)
  473. __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
  474. # if defined __USE_MISC || defined __USE_ISOC99
  475. __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
  476. __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
  477. # endif
  478. __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
  479. #else
  480. __inline_mathop (fabs, "fabs")
  481. __inline_mathop_ (long double, __fabsl, "fabs")
  482. #endif
  483.  
  484. #ifdef __FAST_MATH__
  485. # if !__GNUC_PREREQ (3, 4)
  486. /* The argument range of this inline version is reduced.  */
  487. __inline_mathopNP (sin, "fsin")
  488. /* The argument range of this inline version is reduced.  */
  489. __inline_mathopNP (cos, "fcos")
  490.  
  491. __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
  492. # endif
  493.  
  494. # if !__GNUC_PREREQ (3, 5)
  495. __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
  496.  
  497. __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
  498. __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
  499. # endif
  500.  
  501. # if !__GNUC_PREREQ (3, 4)
  502. __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
  503. # endif
  504. #endif /* __FAST_MATH__ */
  505.  
  506. __inline_mathcode_ (long double, __sgn1l, __x, \
  507.   __extension__ union { long double __xld; unsigned int __xi[3]; } __n =      \
  508.     { __xld: __x };                                  \
  509.   __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff;                  \
  510.   __n.__xi[1] = 0x80000000;                              \
  511.   __n.__xi[0] = 0;                                  \
  512.   return __n.__xld)
  513.  
  514.  
  515. #ifdef __FAST_MATH__
  516. /* The argument range of the inline version of sinhl is slightly reduced.  */
  517. __inline_mathcodeNP (sinh, __x, \
  518.   register long double __exm1 = __expm1l (__fabsl (__x));              \
  519.   return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
  520.  
  521. __inline_mathcodeNP (cosh, __x, \
  522.   register long double __ex = __expl (__x);                      \
  523.   return 0.5 * (__ex + 1.0 / __ex))
  524.  
  525. __inline_mathcodeNP (tanh, __x, \
  526.   register long double __exm1 = __expm1l (-__fabsl (__x + __x));          \
  527.   return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
  528. #endif
  529.  
  530. __inline_mathcodeNP (floor, __x, \
  531.   register long double __value;                              \
  532.   __volatile unsigned short int __cw;                          \
  533.   __volatile unsigned short int __cwtmp;                      \
  534.   __asm __volatile ("fnstcw %0" : "=m" (__cw));                      \
  535.   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */              \
  536.   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                  \
  537.   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));              \
  538.   __asm __volatile ("fldcw %0" : : "m" (__cw));                      \
  539.   return __value)
  540.  
  541. __inline_mathcodeNP (ceil, __x, \
  542.   register long double __value;                              \
  543.   __volatile unsigned short int __cw;                          \
  544.   __volatile unsigned short int __cwtmp;                      \
  545.   __asm __volatile ("fnstcw %0" : "=m" (__cw));                      \
  546.   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */                  \
  547.   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                  \
  548.   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));              \
  549.   __asm __volatile ("fldcw %0" : : "m" (__cw));                      \
  550.   return __value)
  551.  
  552. #ifdef __FAST_MATH__
  553. # define __ldexp_code \
  554.   register long double __value;                              \
  555.   __asm __volatile__                                  \
  556.     ("fscale"                                      \
  557.      : "=t" (__value) : "0" (__x), "u" ((long double) __y));              \
  558.   return __value
  559.  
  560. __MATH_INLINE double
  561. __NTH (ldexp (double __x, int __y))
  562. {
  563.   __ldexp_code;
  564. }
  565. #endif
  566.  
  567.  
  568. /* Optimized versions for some non-standardized functions.  */
  569. #if defined __USE_ISOC99 || defined __USE_MISC
  570.  
  571. # ifdef __FAST_MATH__
  572. __inline_mathcodeNP (expm1, __x, __expm1_code)
  573.  
  574. /* We cannot rely on M_SQRT being defined.  So we do it for ourself
  575.    here.  */
  576. #  define __M_SQRT2    1.41421356237309504880L    /* sqrt(2) */
  577.  
  578. #  if !__GNUC_PREREQ (3, 5)
  579. __inline_mathcodeNP (log1p, __x, \
  580.   register long double __value;                              \
  581.   if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2)                      \
  582.     __value = logl (1.0 + __x);                              \
  583.   else                                          \
  584.     __asm __volatile__                                  \
  585.       ("fldln2\n\t"                                  \
  586.        "fxch\n\t"                                  \
  587.        "fyl2xp1"                                  \
  588.        : "=t" (__value) : "0" (__x) : "st(1)");                      \
  589.   return __value)
  590. #  endif
  591.  
  592.  
  593. /* The argument range of the inline version of asinhl is slightly reduced.  */
  594. __inline_mathcodeNP (asinh, __x, \
  595.   register long double  __y = __fabsl (__x);                      \
  596.   return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y)   \
  597.       * __sgn1l (__x)))
  598.  
  599. __inline_mathcodeNP (acosh, __x, \
  600.   return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
  601.  
  602. __inline_mathcodeNP (atanh, __x, \
  603.   register long double __y = __fabsl (__x);                      \
  604.   return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
  605.  
  606. /* The argument range of the inline version of hypotl is slightly reduced.  */
  607. __inline_mathcodeNP2 (hypot, __x, __y,
  608.               return __libc_sqrtl (__x * __x + __y * __y))
  609.  
  610. #  if !__GNUC_PREREQ (3, 5)
  611. __inline_mathcodeNP(logb, __x, \
  612.   register long double __value;                              \
  613.   register long double __junk;                              \
  614.   __asm __volatile__                                  \
  615.     ("fxtract\n\t"                                  \
  616.      : "=t" (__junk), "=u" (__value) : "0" (__x));                  \
  617.   return __value)
  618. #  endif
  619.  
  620. # endif
  621. #endif
  622.  
  623. #ifdef __USE_ISOC99
  624. # ifdef __FAST_MATH__
  625.  
  626. #  if !__GNUC_PREREQ (3, 5)
  627. __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
  628. #  endif
  629.  
  630. __MATH_INLINE float
  631. __NTH (ldexpf (float __x, int __y))
  632. {
  633.   __ldexp_code;
  634. }
  635.  
  636. __MATH_INLINE long double
  637. __NTH (ldexpl (long double __x, int __y))
  638. {
  639.   __ldexp_code;
  640. }
  641.  
  642. __inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
  643.  
  644. __inline_mathopNP (rint, "frndint")
  645. # endif /* __FAST_MATH__ */
  646.  
  647. # define __lrint_code \
  648.   long int __lrintres;                                  \
  649.   __asm__ __volatile__                                  \
  650.     ("fistpl %0"                                  \
  651.      : "=m" (__lrintres) : "t" (__x) : "st");                      \
  652.   return __lrintres
  653. __MATH_INLINE long int
  654. __NTH (lrintf (float __x))
  655. {
  656.   __lrint_code;
  657. }
  658. __MATH_INLINE long int
  659. __NTH (lrint (double __x))
  660. {
  661.   __lrint_code;
  662. }
  663. __MATH_INLINE long int
  664. __NTH (lrintl (long double __x))
  665. {
  666.   __lrint_code;
  667. }
  668. # undef __lrint_code
  669.  
  670. # define __llrint_code \
  671.   long long int __llrintres;                              \
  672.   __asm__ __volatile__                                  \
  673.     ("fistpll %0"                                  \
  674.      : "=m" (__llrintres) : "t" (__x) : "st");                      \
  675.   return __llrintres
  676. __MATH_INLINE long long int
  677. __NTH (llrintf (float __x))
  678. {
  679.   __llrint_code;
  680. }
  681. __MATH_INLINE long long int
  682. __NTH (llrint (double __x))
  683. {
  684.   __llrint_code;
  685. }
  686. __MATH_INLINE long long int
  687. __NTH (llrintl (long double __x))
  688. {
  689.   __llrint_code;
  690. }
  691. # undef __llrint_code
  692.  
  693. #endif
  694.  
  695.  
  696. #ifdef __USE_MISC
  697.  
  698. # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
  699. __inline_mathcodeNP2 (drem, __x, __y, \
  700.   register double __value;                              \
  701.   register int __clobbered;                              \
  702.   __asm __volatile__                                  \
  703.     ("1:    fprem1\n\t"                              \
  704.      "fstsw    %%ax\n\t"                              \
  705.      "sahf\n\t"                                      \
  706.      "jp    1b"                                  \
  707.      : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc");    \
  708.   return __value)
  709. # endif
  710.  
  711.  
  712. /* This function is used in the `isfinite' macro.  */
  713. __MATH_INLINE int
  714. __NTH (__finite (double __x))
  715. {
  716.   return (__extension__
  717.       (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
  718.          | 0x800fffffu) + 1) >> 31));
  719. }
  720.  
  721. /* Miscellaneous functions */
  722. # ifdef __FAST_MATH__
  723. __inline_mathcode (__coshm1, __x, \
  724.   register long double __exm1 = __expm1l (__fabsl (__x));              \
  725.   return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
  726.  
  727. __inline_mathcode (__acosh1p, __x, \
  728.   return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
  729.  
  730. # endif /* __FAST_MATH__ */
  731. #endif /* __USE_MISC  */
  732.  
  733. /* Undefine some of the large macros which are not used anymore.  */
  734. #undef __atan2_code
  735. #ifdef __FAST_MATH__
  736. # undef __expm1_code
  737. # undef __exp_code
  738. # undef __sincos_code
  739. #endif /* __FAST_MATH__ */
  740.  
  741. #endif /* __NO_MATH_INLINES  */
  742.  
  743.  
  744. /* This code is used internally in the GNU libc.  */
  745. #ifdef __LIBC_INTERNAL_MATH_INLINES
  746. __inline_mathop (__ieee754_sqrt, "fsqrt")
  747. __inline_mathcode2 (__ieee754_atan2, __y, __x,
  748.             register long double __value;
  749.             __asm __volatile__ ("fpatan\n\t"
  750.                     : "=t" (__value)
  751.                     : "0" (__x), "u" (__y) : "st(1)");
  752.             return __value;)
  753. #endif
  754.  
  755. #endif /* __GNUC__  */
  756.